We are migrating the bug tracker to github Issues. This is now the preferred way to report NASM bugs.

Self-registration is disabled due to spam issue (mail gorcunov@gmail.com or hpa@zytor.com to create an account)

Bug 3392922 - Double dollar sign prefix should be allowed, to specify a label with one dollar sign in the object file
Summary: Double dollar sign prefix should be allowed, to specify a label with one doll...
Status: CLOSED FIXED
Alias: None
Product: NASM
Classification: Unclassified
Component: Assembler (show other bugs)
Version: new feature request
Hardware: All All
: Medium normal
Assignee: nobody
URL:
Depends on:
Blocks:
 
Reported: 2024-11-02 06:39 PDT by E. C. Masloch
Modified: 2025-09-03 01:21 PDT (History)
5 users (show)

Obtained from: Built from git using configure
Generated by: Human
Bug category: Incorrect main output, Unexpected or confusing behavior
Observed for: Invalid input
Regression: No
Regression since:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description E. C. Masloch 2024-11-02 06:39:01 PDT
During my work on porting the MS-DOS v4.01 msdos kernel module I came across a symbol that uses a dollar sign prefix to distinguish it from an equate. NASM doesn't allow this as it interprets the dollar sign as an escape code.

Unfortunately, NASM doesn't support escaping the dollar sign as a literal by prefixing another dollar sign. That means I have to modify the original sources to use another workaround, and cannot link the NASM-produced object file with the other original object files as they have the dollar sign in the object files.

Test case:

$ cat test.asm

section .text
        global $test
$test:
        global FOO
FOO:
$ nasm -v
NASM version 2.16.02rc2 compiled on Oct 12 2023
$ nasm -fobj test.asm
$ nasm test.asm -fobj -DFOO=\$\$foo
test.asm:5: error: identifier expected after global, got `$foo'
test.asm:6: error: label or instruction expected at start of line
$
Comment 1 E. C. Masloch 2024-11-04 08:35:48 PST
I ended up running a script on the original (to-be-ported) files that detects all the uses of dollar-sign-prefixed symbols and replaces the dollar sign by the string "D_". Then I rebuilt all object files using the original toolchain to aid my subsequent porting work.

Reference: https://hg.pushbx.org/ecm/msdos4/rev/fda58d7d795b

Scriptlet used to generate these changes:

hg up -C &&
  perl -i -pe '
  s/^(\s*(?:procedure|endproc|jn?[ezcbalgpos]e?|jmp|jcxz|call|loopn?[ez]?|invoke|entry|transfer|short_addr|DW\s*OFFSET\s*DOSGroup:|)\s*(?:short|near)?\s*)\$/$1D_/i
  ' src/DOS/*.ASM src/CMD/SHARE/*.ASM src/CMD/IFSFUNC/*.ASM
Comment 2 E. C. Masloch 2025-09-01 10:02:37 PDT
Would be nice if I could port WarpLink's overlay manager to NASM without major hacks, but it uses many symbol names with double-dollar prefixes: https://hg.pushbx.org/ecm/warplink/file/a1a5e4378c92/OVLMGR.ASM
Comment 3 E. C. Masloch 2025-09-01 11:17:02 PDT
I went and added a replacement of leading "D." to '$' to our fixupp utility: https://hg.pushbx.org/ecm/fixupp/rev/07e8e8cbf669
Comment 4 H. Peter Anvin 2025-09-02 18:17:41 PDT
I have checked in a fix for this onto the apx.wip branch, which should become the master branch soon.
Comment 5 E. C. Masloch 2025-09-02 22:39:45 PDT
Doesn't seem to work:

test$ cat test.asm
section $$$bar
global $foo
global $$foo
global $$$foo

$foo:
$$foo:
$$$foo:
test$ ~/proj/nasmwip/nasm test.asm -fobj
test.asm:3: error: identifier expected after global, got `$foo'
test.asm:4: error: identifier expected after global, got `$$foo'
test.asm:6: error: label, instruction or prefix expected at start of line, found `$foo'
test$
Comment 6 H. Peter Anvin 2025-09-02 23:25:07 PDT
Oh bloody hell.

This is a totally different problem, which seems to date back to the very beginning of NASM.

A dollar sign doesn't work to escape an identifier that begins with the letters A-F, because it is misinterpreted as the beginning of a hexadecimal constant.

The worst part is that it is basically unfixable without breaking existing code, because, for example, $A0 could be the hexadecimal constant 0xa0 or the escaped symbol A0; but then again, the current behavior is also broken and arguably in a far worse way.

I think I might simply want to add an option to disable hexadecimal numbers starting with $...
Comment 7 E. C. Masloch 2025-09-03 00:04:01 PDT
But then I would expect a different test to succeed, one where there's an underscore after the dollar sign. But that fails too:

test$ cat test2.asm
section $$$_bar
global $_foo
global $$_foo
global $$$_foo

$_foo:
$$_foo:
$$$_foo:
test$ ~/proj/nasmwip/nasm test2.asm -fobj
test2.asm:3: error: identifier expected after global, got `$_foo'
test2.asm:4: error: identifier expected after global, got `$$_foo'
test2.asm:6: error: label, instruction or prefix expected at start of line, found `
$_foo'
test$
Comment 8 H. Peter Anvin 2025-09-03 00:38:00 PDT
I just checked in a patch that adds a new directive:

[dollarhex off]

... which disables the $ prefix syntax for hexadecimal numbers and thus properly treats "$foo" as the escaped version of "foo".  As a side benefit this allows symbols starting with digits, e.g. "$3".
Comment 9 H. Peter Anvin 2025-09-03 00:39:16 PDT
There was also a problem with the handling of symbol names in directives (global, static, extern, required, common, debug) which I also fixed.
Comment 10 H. Peter Anvin 2025-09-03 00:40:26 PDT
Underscores are allowed as separators in numbers, thus $_33 = 0x_33 = 33 hex.
Comment 11 E. C. Masloch 2025-09-03 00:48:52 PDT
> Underscores are allowed as separators in numbers, thus $_33 = 0x_33 = 33 hex.

Yes, but absent the dollar sign a "number" like _1 is valid as a label. So I expected $_foo to also be valid without [dollarhex off].

My test cases do assemble with a leading [dollarhex off]. However, section $$$_bar (with three dollars) results in a section called $$$_bar in the object file (three dollars) where I expected $$_bar (two dollars).
Comment 12 H. Peter Anvin 2025-09-03 00:54:42 PDT
Yes, section names are not symbols and so their names are and have always been literal.

I don't think it makes sense to try to futz with the specifics of the $hex syntax; the right thing is to get rid of it.
Comment 13 E. C. Masloch 2025-09-03 01:00:20 PDT
Okay, but using the section name like a symbol requires one more dollar sign than was specified to the section directive. If you're fine with that then we can consider this done. Test case:

test$ cat test4.asm

section $$qux

        dw $$qux
test$ cat test5.asm

section $$qux

        dw $$$qux
test$ ~/proj/nasmwip/nasm test4.asm -fobj
test4.asm:4: error: symbol `$qux' not defined
test$ ~/proj/nasmwip/nasm test5.asm -fobj
test$
Comment 14 H. Peter Anvin 2025-09-03 01:21:12 PDT
Well, it is legacy behavior and breaking it is likely to cause more headache than it is worth.

I did, however, note that the documentation does specify that $hex is only permitted when the first character is a digit like the -h suffix (which is VERY weird...) so I have changed the code to actually match what is documented; this cuts down on the conflict at least.